/*
 * PhotonRTOS础光实时操作系统 -- 中断实现
 *
 * Copyright (C) 2022, 2023, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <photon/init.h>
#include <photon/sched.h>

#include <asm/irq.h>
#include <asm/irqflags.h>
#include <asm/internel.h>
#include <generated/asm-offsets.h>


uint32_t g_context_szie = THREAD_CPU_CONTEXT;

#define ASM_PRINTK_SYS_PROC_INFO				\
	asm volatile(						\
	"MRS  %r3,CPSR \n"					\
	"MRS  %r2,CPSR \n"					\
	"BIC  %r2,#0X1f \n"					\
	"ORR  %r2,#0x1f \n"					\
	"MSR  CPSR_c, %r2 \n"					\
								\
	"MOV  %0, SP \n"					\
	"MOV  %1, LR \n"					\
								\
	"MSR  CPSR_c,%r3 \n"					\
	:"=r" (sp_usr),"=r" (lr_usr), "=r"(tmp),"=r"(tmp1)	\
	::"memory","cc");

void (*handle_arch_irq)(void *regs) = NULL;

asmlinkage void arch_switch_cpu_context(struct task_desc *prev,
	struct task_desc *next)
{
	__asm volatile (
		".fnstart		\n"
		".cantunwind	\n"
		"ldr ip, =g_context_szie \n"
		"ldr ip, [ip] \n"
		"add ip, ip, r0 \n"
		"stmia	ip!, {r4 - r11} 	@ Store most regs on stack \n"
		"str sp, [ip], #4 \n"
		"str lr, [ip], #4 \n"
		"ldr r4, =g_context_szie \n"
		"ldr r4, [r4] \n"
		"add r4, r4, r1 \n"
		"mov ip, r4\n"
		"ldmia	ip!, {r4 - r11} 	@ Load all regs saved previously\n"
		"ldr sp, [ip]\n"
		"add sp, #8\n"
		"ldr pc, [ip, #4]!\n"
	);
}
/**
 * 设置中断处理函数
 * 如gic_handle_irq
 */
void set_chip_irq_handle(void (*handle_irq)(void *regs))
{
	if (handle_arch_irq == NULL) {
		handle_arch_irq = handle_irq;
	}
}

#if defined(CONFIG_CPU_CORTEX_R)
static void printk_sys_proc_info(void)
{
	register uintptr_t sp asm("sp");

	register uintptr_t sp_usr;
	register uintptr_t lr_usr;
	uintptr_t tmp, tmp1;

	printk("\nnow sp = 0x%x\n",sp);

	ASM_PRINTK_SYS_PROC_INFO;

	printk("\nsp_usr = 0x%x\n",sp_usr);
	printk("\nlr_usr = 0x%x\n",lr_usr);
	return;
}

void handle_R5_irq (void);
void handle_R5_irq (void)
{
	if (handle_arch_irq != NULL) {
		handle_arch_irq(NULL);
	}
}

void handle_arch_fiq (void);
void handle_arch_fiq (void)
{
	printk( "\nfiq comming");
}


void swi_main (void);
void swi_main (void)
{
	printk( "\nswi comming");
}

void dabort_main (uint32_t lr,uint32_t sp);

void dabort_main (uint32_t lr,uint32_t sp)
{
	printk( "\ndabort comming");
	printk_sys_proc_info();
	while ( true )
	{
	}
}

void pabort_main (void);
void pabort_main (void)
{
	printk("\nprefech abort exception error");
	printk_sys_proc_info();
	while ( true )
	{
	}
}

void undef_main (void);
void undef_main (void)
{
	printk("\nundef exception error");
	printk_sys_proc_info();
	while ( true )
	{
	}
}

void arch_task_init(void *stack, void* func, void *task)
{
	struct task_desc *tsk = (struct task_desc *)task;
	tsk->task_spot.cpu_context.fp = 0;
	tsk->task_spot.cpu_context.sp =
			(uintptr_t)stack + (uintptr_t)THREAD_START_SP;
	tsk->task_spot.cpu_context.pc = (uint32_t)func;
}

#endif
#if defined(CONFIG_CPU_CORTEX_M)
void arch_task_init(void *stack, void* func, void *task)
{
	struct task_desc *tsk = (struct task_desc *)task;
	tsk->task_spot.cpu_context.fp = 0;
	tsk->task_spot.cpu_context.sp =
			(uintptr_t)stack + (uintptr_t)THREAD_START_SP;
	tsk->task_spot.cpu_context.pc = (uint32_t)func;
}
#endif
